home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / lysrc.zip / LEXTABLE.PAS < prev    next >
Pascal/Delphi Source File  |  1993-01-24  |  14KB  |  452 lines

  1.  
  2. unit LexTables;
  3.  
  4. (* 2-5-91 AG
  5.    5-13-92 AG (bug fix in merge_trans) *)
  6.  
  7. (* Copyright (c) 1990,91 by Albert Graef, Schillerstr. 18,
  8.    6509 Schornsheim/Germany
  9.    All rights reserved *)
  10.  
  11. interface
  12.  
  13. uses LexBase;
  14.  
  15. (* This module collects the various tables used by the Lex program:
  16.    - the symbol table
  17.    - the position table
  18.    - the DFA states and transition tables
  19.    Note: All tables are allocated dynamically (at initialization time)
  20.    because of the 64KB static data limit. *)
  21.  
  22. var max_bytes : LongInt;
  23.   (* available memory *)
  24.  
  25. function n_bytes : LongInt;
  26.   (* memory actually used *)
  27.  
  28. const
  29.  
  30. (* Maximum table sizes: *)
  31.  
  32. max_keys           =  997;  (* size of hash symbol table (prime number!)   *)
  33. max_pos            =  600;  (* maximum number of positions                 *)
  34. max_states         =  300;  (* number of DFA states                        *)
  35. max_trans          =  600;  (* number of transitions                       *)
  36. max_start_states   =   50;  (* maximum number of user-defined start states *)
  37.  
  38. var
  39.  
  40. (* Actual table sizes: *)
  41.  
  42. n_pos            : Integer;
  43. n_states         : Integer;
  44. n_trans          : Integer;
  45. n_start_states   : Integer;
  46.  
  47. type
  48.  
  49. (* Table data structures: *)
  50.  
  51. SymTable = array [1..max_keys] of record
  52.              pname  : StrPtr;
  53.                (* print name; empty entries are denoted by pname=nil *)
  54.              case sym_type : ( none, macro_sym, start_state_sym ) of
  55.              macro_sym : ( subst : StrPtr );
  56.                (* macro substitution *)
  57.              start_state_sym : ( start_state : Integer );
  58.                (* start state *)
  59.            end;
  60.  
  61. PosTableEntry = record
  62.                   follow_pos    : IntSetPtr;
  63.                     (* set of follow positions *)
  64.                   case pos_type : ( char_pos, cclass_pos, mark_pos ) of
  65.                   char_pos      : ( c   : Char );
  66.                     (* character position *)
  67.                   cclass_pos    : ( cc  : CClassPtr );
  68.                     (* character class position *)
  69.                   mark_pos      : ( rule, pos : Integer );
  70.                     (* mark position *)
  71.                 end;
  72.  
  73. PosTable = array [1..max_pos] of PosTableEntry;
  74.  
  75. FirstPosTable  = array [0..2*max_start_states+1] of IntSetPtr;
  76.                    (* first positions for start states (even states
  77.                       are entered anywhere on the line, odd states only
  78.                       at the beginning of the line; states 0 and 1 denote
  79.                       default, states 2..2*n_start_states+1 user-defined
  80.                       start states) *)
  81.  
  82. StateTableEntry = record
  83.                     state_pos : IntSetPtr;
  84.                       (* positions covered by state *)
  85.                     final     : Boolean;
  86.                       (* final state? *)
  87.                     trans_lo,
  88.                     trans_hi  : Integer;
  89.                       (* transitions *)
  90.                   end;
  91.  
  92. StateTable = array [0..max_states-1] of StateTableEntry;
  93.  
  94. TransTableEntry = record
  95.                     cc              : CClassPtr;
  96.                       (* characters of transition *)
  97.                     follow_pos      : IntSetPtr;
  98.                       (* follow positions (positions of next state) *)
  99.                     next_state      : Integer;
  100.                       (* next state *)
  101.                   end;
  102.  
  103. TransTable = array [1..max_trans] of TransTableEntry;
  104.  
  105.  
  106. var
  107.  
  108. verbose           : Boolean;          (* status of the verbose option *)
  109. optimize          : Boolean;          (* status of the optimization option *)
  110.  
  111. sym_table         : ^SymTable;        (* symbol table *)
  112. pos_table         : ^PosTable;        (* position table *)
  113. first_pos_table   : ^FirstPosTable;   (* first positions table *)
  114. state_table       : ^StateTable;      (* DFA state table *)
  115. trans_table       : ^TransTable;      (* DFA transition table *)
  116.  
  117.  
  118. (* Operations: *)
  119.  
  120. (* Hash symbol table:
  121.    The following routines are supplied to be used with the generic hash table
  122.    routines in LexBase. *)
  123.  
  124. function lookup(k : Integer) : String;
  125.   (* print name of symbol no. k *)
  126. procedure entry(k : Integer; symbol : String);
  127.   (* enter symbol into table *)
  128.  
  129. (* Routines to build the position table: *)
  130.  
  131. procedure addCharPos(c : Char);
  132. procedure addCClassPos(cc : CClassPtr);
  133. procedure addMarkPos(rule, pos : Integer);
  134.   (* Positions are allocated in the order of calls to addCharPos, addCClassPos
  135.      and addMarkPos, starting at position 1. These routines also initialize
  136.      the corresponding follow sets. *)
  137.  
  138. (* Routines to build the state table: *)
  139.  
  140. var act_state : Integer; (* state currently considered *)
  141.  
  142. function newState(POS : IntSetPtr) : Integer;
  143.   (* Add a new state with the given position set; initialize the state's
  144.      position set to POS (the offsets into the transition table are
  145.      initialized when the state becomes active, see startStateTrans, below).
  146.      Returns: the new state number *)
  147.  
  148. function addState(POS : IntSetPtr) : Integer;
  149.   (* add a new state, but only if there is not already a state with the
  150.      same position set *)
  151.  
  152. procedure startStateTrans;
  153. procedure endStateTrans;
  154.   (* initializes act_state's first and last offsets into the transition
  155.      table *)
  156.  
  157. function n_state_trans(i : Integer) : Integer;
  158.   (* return number of transitions in state i *)
  159.  
  160. procedure addTrans(cc : CClass; FOLLOW : IntSetPtr);
  161.   (* adds a transition to the table *)
  162.  
  163. procedure mergeTrans;
  164.   (* sorts transitions w.r.t. next states and merges transitions for the
  165.      same next state in the active state *)
  166.  
  167. procedure sortTrans;
  168.   (* sort transitions in act_state lexicographically *)
  169.  
  170. implementation
  171.  
  172. uses LexMsgs;
  173.  
  174. function n_bytes : LongInt;
  175.   begin
  176.     n_bytes := max_bytes-memAvail
  177.   end(*n_bytes*);
  178.  
  179. (* Hash table routines: *)
  180.  
  181. function lookup(k : Integer) : String;
  182.   begin
  183.     with sym_table^[k] do
  184.       if pname=nil then
  185.         lookup := ''
  186.       else
  187.         lookup := copy(pname^, 1, length(pname^))
  188.   end(*lookup*);
  189. procedure entry(k : Integer; symbol : String);
  190.   begin
  191.     with sym_table^[k] do
  192.       begin
  193.         pname    := newStr(symbol);
  194.         sym_type := none;
  195.       end
  196.   end(*entry*);
  197.  
  198. (* Routines to build the position table: *)
  199.  
  200. procedure addCharPos(c : Char);
  201.   begin
  202.     inc(n_pos);
  203.     if n_pos>max_pos then fatal(pos_table_overflow);
  204.     pos_table^[n_pos].follow_pos     := newIntSet;
  205.     pos_table^[n_pos].pos_type       := char_pos;
  206.     pos_table^[n_pos].c              := c;
  207.   end(*addCharPos*);
  208.  
  209. procedure addCClassPos(cc : CClassPtr);
  210.   begin
  211.     inc(n_pos);
  212.     if n_pos>max_pos then fatal(pos_table_overflow);
  213.     pos_table^[n_pos].follow_pos     := newIntSet;
  214.     pos_table^[n_pos].pos_type       := cclass_pos;
  215.     pos_table^[n_pos].cc             := cc;
  216.   end(*addCClassPos*);
  217.  
  218. procedure addMarkPos(rule, pos : Integer);
  219.   begin
  220.     inc(n_pos);
  221.     if n_pos>max_pos then fatal(pos_table_overflow);
  222.     pos_table^[n_pos].follow_pos     := newIntSet;
  223.     pos_table^[n_pos].pos_type       := mark_pos;
  224.     pos_table^[n_pos].rule           := rule;
  225.     pos_table^[n_pos].pos            := pos;
  226.   end(*addMarkPos*);
  227.  
  228. (* Routines to build the state table: *)
  229.  
  230. function newState(POS : IntSetPtr) : Integer;
  231.   begin
  232.     if n_states>=max_states then fatal(state_table_overflow);
  233.     newState := n_states;
  234.     with state_table^[n_states] do
  235.       begin
  236.         state_pos := POS;
  237.         final     := false;
  238.       end;
  239.     inc(n_states);
  240.   end(*newState*);
  241.  
  242. function addState(POS : IntSetPtr) : Integer;
  243.   var i : Integer;
  244.   begin
  245.     for i := 0 to pred(n_states) do
  246.       if equal(POS^, state_table^[i].state_pos^) then
  247.         begin
  248.           addState := i;
  249.           exit;
  250.         end;
  251.     addState := newState(POS);
  252.   end(*addState*);
  253.  
  254. procedure startStateTrans;
  255.   begin
  256.     state_table^[act_state].trans_lo := succ(n_trans);
  257.   end(*startStateTrans*);
  258.  
  259. procedure endStateTrans;
  260.   begin
  261.     state_table^[act_state].trans_hi := n_trans;
  262.   end(*endStateTrans*);
  263.  
  264. function n_state_trans(i : Integer) : Integer;
  265.   begin
  266.     with state_table^[i] do
  267.       n_state_trans := trans_hi-trans_lo+1
  268.   end(*n_state_trans*);
  269.  
  270. (* Construction of the transition table:
  271.    This implementation here uses a simple optimization which tries to avoid
  272.    the construction of different transitions for each individual character
  273.    in large character classes by MERGING transitions whenever possible. The
  274.    transitions, at any time, will be partitioned into transitions on disjoint
  275.    character classes. When adding a new transition on character class cc, we
  276.    repartition the transitions as follows:
  277.    1. If the current character class cc equals an existing one, we can
  278.       simply add the new follow set to the existing one.
  279.    2. Otherwise, for some existing transition on some character class
  280.       cc1 with cc*cc1<>[], we replace the existing transition by a new
  281.       transition on cc*cc1 with follow set = cc1's follow set + cc's follow
  282.       set, and, if necessary (i.e. if cc1-cc is nonempty), a transition on
  283.       cc1-cc with follow set = cc1's follow set. We then remove the elements
  284.       of cc1 from cc, and proceed again with step 1.
  285.    We may stop this process as soon as cc becomes empty (then all characters
  286.    in cc have been distributed among the existing partitions). If cc does
  287.    NOT become empty, we have to construct a new transition for the remaining
  288.    character class (which then will be disjoint from all other character
  289.    classes in the transition table). *)
  290.  
  291. procedure addTrans(cc : CClass; FOLLOW : IntSetPtr);
  292.   var
  293.     i : Integer;
  294.     cc0, cc1, cc2 : CClass;
  295.   begin
  296.     for i := state_table^[act_state].trans_lo to n_trans do
  297.       if trans_table^[i].cc^=cc then
  298.         begin
  299.           setunion(trans_table^[i].follow_pos^, FOLLOW^);
  300.           exit
  301.         end
  302.       else
  303.         begin
  304.           cc0 := cc*trans_table^[i].cc^;
  305.           if cc0<>[] then
  306.             begin
  307.               cc1 := trans_table^[i].cc^-cc;
  308.               cc2 := cc-trans_table^[i].cc^;
  309.               if cc1<>[] then
  310.                 begin
  311.                   trans_table^[i].cc^ := cc1;
  312.                   inc(n_trans);
  313.                   if n_trans>max_trans then fatal(trans_table_overflow);
  314.                   trans_table^[n_trans].cc := newCClass(cc0);
  315.                   trans_table^[n_trans].follow_pos := newIntSet;
  316.                   trans_table^[n_trans].follow_pos^ :=
  317.                     trans_table^[i].follow_pos^;
  318.                   setunion(trans_table^[n_trans].follow_pos^, FOLLOW^);
  319.                 end
  320.               else
  321.                 begin
  322.                   trans_table^[i].cc^ := cc0;
  323.                   setunion(trans_table^[i].follow_pos^, FOLLOW^);
  324.                 end;
  325.               cc := cc2;
  326.               if cc=[] then exit;
  327.             end
  328.         end;
  329.     inc(n_trans);
  330.     if n_trans>max_trans then fatal(trans_table_overflow);
  331.     trans_table^[n_trans].cc          := newCClass(cc);
  332.     trans_table^[n_trans].follow_pos  := newIntSet;
  333.     trans_table^[n_trans].follow_pos^ := FOLLOW^;
  334.   end(*addCharTrans*);
  335.  
  336. (* comparison and swap procedures for sorting transitions: *)
  337. {$F+}
  338. function transLessNextState(i, j : Integer) : Boolean;
  339. {$F-}
  340.   (* compare transitions based on next states (used in mergeCharTrans) *)
  341.   begin
  342.     transLessNextState := trans_table^[i].next_state<
  343.                           trans_table^[j].next_state
  344.   end(*transLessNextState*);
  345. {$F+}
  346. function transLess(i, j : Integer) : Boolean;
  347. {$F-}
  348.   (* lexical order on transitions *)
  349.   var c : Char; xi, xj : Boolean;
  350.   begin
  351.     for c := #0 to #255 do
  352.       begin
  353.         xi := c in trans_table^[i].cc^;
  354.         xj := c in trans_table^[j].cc^;
  355.         if xi<>xj then
  356.           begin
  357.             transLess := xi>xj;
  358.             exit
  359.           end;
  360.       end;
  361.     transLess := false
  362.   end(*transLess*);
  363. {$F+}
  364. procedure transSwap(i, j : Integer);
  365. {$F-}
  366.   (* swap transitions i and j *)
  367.   var x : TransTableEntry;
  368.   begin
  369.     x := trans_table^[i];
  370.     trans_table^[i] := trans_table^[j];
  371.     trans_table^[j] := x;
  372.   end(*transSwap*);
  373.  
  374. procedure mergeTrans;
  375.   var
  376.     i, j, n_deleted : Integer;
  377.   begin
  378.     (* sort transitions w.r.t. next states: *)
  379.     quicksort(state_table^[act_state].trans_lo,
  380.               n_trans,
  381.               transLessNextState,
  382.               transSwap);
  383.     (* merge transitions for the same next state: *)
  384.     n_deleted := 0;
  385.     for i := state_table^[act_state].trans_lo to n_trans do
  386.     if trans_table^[i].cc<>nil then
  387.       begin
  388.         j := succ(i);
  389.         while (j<=n_trans) and
  390.               (trans_table^[i].next_state =
  391.                trans_table^[j].next_state) do
  392.           begin
  393.             (* merge cclasses of transitions i and j, then mark
  394.                transition j as deleted *)
  395.             trans_table^[i].cc^ := trans_table^[i].cc^+
  396.                                    trans_table^[j].cc^;
  397.             trans_table^[j].cc  := nil;
  398.             inc(n_deleted);
  399.             inc(j);
  400.           end;
  401.       end;
  402.     (* remove deleted transitions: *)
  403.     j := state_table^[act_state].trans_lo;
  404.     for i := state_table^[act_state].trans_lo to n_trans do
  405.       if trans_table^[i].cc<>nil then
  406.         if i<>j then
  407.           begin
  408.             trans_table^[j] := trans_table^[i];
  409.             inc(j);
  410.           end
  411.         else
  412.           inc(j);
  413.     (* update transition count: *)
  414.     dec(n_trans, n_deleted);
  415.   end(*mergeTrans*);
  416.  
  417. procedure sortTrans;
  418.   begin
  419.     quicksort(state_table^[act_state].trans_lo,
  420.               n_trans,
  421.               transLess,
  422.               transSwap);
  423.   end(*sortTrans*);
  424.  
  425. var i : Integer;
  426.  
  427. begin
  428.  
  429.   verbose          := false;
  430.   optimize         := false;
  431.  
  432.   max_bytes        := memAvail;
  433.  
  434.   n_pos            := 0;
  435.   n_states         := 0;
  436.   n_trans          := 0;
  437.   n_start_states   := 0;
  438.  
  439.   (* allocate tables: *)
  440.  
  441.   new(sym_table);
  442.   new(pos_table);
  443.   new(first_pos_table);
  444.   new(state_table);
  445.   new(trans_table);
  446.  
  447.   (* initialize symbol table: *)
  448.  
  449.   for i := 1 to max_keys do sym_table^[i].pname := nil;
  450.  
  451. end(*LexTables*).
  452.